/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.udt.designtime.api.entity;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.inspur.edp.caf.cef.schema.base.structure.impl.DefaultValueObject;
import com.inspur.edp.caf.cef.schema.datatype.StructuredType;
import com.inspur.edp.caf.cef.schema.datatype.ValueObjectType;
import com.inspur.edp.caf.cef.schema.element.Operation;
import com.inspur.edp.caf.cef.schema.element.Property;
import com.inspur.edp.caf.cef.schema.structure.CommonStructure;
import com.inspur.edp.caf.cef.schema.structure.ValueObject;
import com.inspur.edp.cef.designtime.api.entity.*;
import com.inspur.edp.lcm.metadata.api.AbstractMetadataContent;
import com.inspur.edp.lcm.metadata.api.IMetadataContent;
import com.inspur.edp.udt.designtime.api.commonstructure.UdtCommonStructureUtil;
import com.inspur.edp.udt.designtime.api.entity.dbInfo.ColumnCollection;
import com.inspur.edp.udt.designtime.api.entity.enumtype.UseType;
import com.inspur.edp.udt.designtime.api.entity.property.PropertyCollection;
import com.inspur.edp.udt.designtime.api.entity.property.PropertyInfo;
import com.inspur.edp.udt.designtime.api.entity.validation.UdtTriggerTimePointType;
import com.inspur.edp.udt.designtime.api.entity.validation.ValidationCollection;
import com.inspur.edp.udt.designtime.api.extension.BaseUdtExtension;
import com.inspur.edp.udt.designtime.api.utils.UdtUtils;
import com.inspur.edp.cef.designtime.api.IGspCommonDataType;
import com.inspur.edp.cef.designtime.api.IFieldCollection;
import com.inspur.edp.cef.designtime.api.collection.CommonDtmCollection;
import com.inspur.edp.cef.designtime.api.collection.CommonValCollection;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * UDT基类
 */
public class UnifiedDataTypeDef extends AbstractMetadataContent implements IGspCommonDataType, IMetadataContent, ValueObject, ValueObjectType {

	private TransmitType transmitType = TransmitType.ValueChanged;

	private CommonDtmCollection dtmBeforeSave;
	private CommonDtmCollection dtmAfterCreate;
	private CommonDtmCollection dtmAfterModify;
	private CommonValCollection valBeforeSave;
	private CommonValCollection valAfterModify;

	// region 属性
	/**
	 * 唯一标识
	 * <see cref="string"/>
	 */
	private String privateId;

	public final String getId() {
		return privateId;
	}

	public final void setId(String value) {
		privateId = value;
	}

	/**
	 * 编号
	 * <see cref="string"/>
	 */
	private String privateCode;

	public final String getCode() {
		this.privateCode = super.getCode();
		return privateCode;
	}

	public final void setCode(String value) {
		super.setCode(value);
		privateCode = value;
	}

	/**
	 * 名称
	 * <see cref="string"/>
	 */
	private String privateName;

	public final String getName() {
		this.privateName = super.getName();
		return privateName;
	}

	public final void setName(String value) {
		super.setName(value);
		privateName = value;
	}

	/**
	 * 标签
	 * <see cref="string"/>
	 */
	private List<String> beLabel;
	public List<String> getBeLabel() {
		if(beLabel==null){
			beLabel=new ArrayList<String>();
			return beLabel;
		}
		return beLabel;
	}


	public void setBeLabel(List<String> value) {
		beLabel=value;
	}


  @Override
  public List<String> getBizTagIds() {
    return null;
  }

  @Override
  public void setBizTagIds(List<String> list) {

  }

  @Override
  public boolean isBigNumber() {
    return false;
  }

  @Override
  public void setIsBigNumber(boolean b) {

  }

  /**
	 * 描述
	 * <see cref="string"/>
	 */
	private String privateDescription;

	public final String getDescription() {
		return privateDescription;
	}

	public final void setDescription(String value) {
		privateDescription = value;
	}

	/**
	 * 创建人
	 * <see cref="string"/>
	 */
	private String privateCreator;

	public final String getCreator() {
		return privateCreator;
	}

	public final void setCreator(String value) {
		privateCreator = value;
	}

// todo: Cef runtime 引用
//	/**
//	 * 创建时间
//	 * <see cref="DateTime"/>
//	 */
//	@JsonDeserialize(using = com.inspur.edp.cef.spi.jsonser.abstractcefchange.BefDateTimeDeseiralizer.class)
//	@JsonSerialize(using = com.inspur.edp.cef.spi.jsonser.abstractcefchange.BefDateTimeSerializer.class)
//	private java.util.Date privateCreatedDate = new java.util.Date(0);
//
//	public final java.util.Date getCreatedDate() {
//		return privateCreatedDate;
//	}
//
//	public final void setCreatedDate(java.util.Date value) {
//		privateCreatedDate = value;
//	}

	/**
	 * 最后修改人
	 * <see cref="string"/>
	 */
	private String privateModifier;

	public final String getModifier() {
		return privateModifier;
	}

	public final void setModifier(String value) {
		privateModifier = value;
	}
// todo: Cef runtime 引用
//	/**
//	 * 最后修改时间
//	 * <see cref="DateTime"/>
//	 */
//	@JsonDeserialize(using = com.inspur.edp.cef.spi.jsonser.abstractcefchange.BefDateTimeDeseiralizer.class)
//	@JsonSerialize(using = com.inspur.edp.cef.spi.jsonser.abstractcefchange.BefDateTimeSerializer.class)
//	private java.util.Date privateModifiedDate = new java.util.Date(0);
//
//	public final java.util.Date getModifiedDate() {
//		return privateModifiedDate;
//	}
//
//	public final void setModifiedDate(java.util.Date value) {
//		privateModifiedDate = value;
//	}

	/**
	 * 程序集名，供JIT使用，默认是元数据命名空间
	 * <see cref="string"/>
	 */
	private String privateAssemblyName;

	public final String getAssemblyName() {
		return privateAssemblyName;
	}

	public final void setAssemblyName(String value) {
		privateAssemblyName = value;
	}

	private String privateDotnetAssemblyName;

	public final String getDotnetAssemblyName() {
		return privateDotnetAssemblyName;
	}

	public final void setDotnetAssemblyName(String value) {
		privateDotnetAssemblyName = value;
	}

	private java.util.HashMap<String, UseTypeInfo> propertyTypeInfos;

	private Map<String, BaseUdtExtension> udtExtensions=new HashMap<>();

	/**
	 * 属性使用方式信息集合
	 */
	public final java.util.HashMap<String, UseTypeInfo> getPropertyUseTypeInfos() {
		if (propertyTypeInfos == null) {
			propertyTypeInfos = new java.util.HashMap<String, UseTypeInfo>();
		}
		return propertyTypeInfos;
	}

	private PropertyCollection propertys;

	/**
	 * 属性集合
	 * <see cref="PropertyCollection"/>
	 */
	public final PropertyCollection getPropertys() {
		if (propertys == null) {
			propertys = new PropertyCollection();
		}
		return propertys;
	}

	private ValidationCollection privateValidations;

	/**
	 * 校验规则
	 * <see cref="ValidationCollection"/>
	 */
	public ValidationCollection getValidations() {
		if (privateValidations == null) {
			privateValidations = new ValidationCollection();
			return privateValidations;
		}

		return privateValidations;

	}


	/*
	 （IGspCommonDataType）标识符
	 <see cref="string"/>
	 
	*/
	public String getID() {
		return getId();
	}

	public void setID(String value) {
		setId(value);
	}

	/**
	 * 字段集合（仅多值udt包含）
	 * <see cref="IFieldCollection"/>
	 */


	public IFieldCollection getContainElements() {
		throw new NotImplementedException();
	}

	/**
	 * 是否引用对象
	 * <see cref="bool"/>
	 */
	private boolean privateIsRef;

	public boolean getIsRef() {
		return privateIsRef;
	}

	public void setIsRef(boolean value) {
		privateIsRef = value;
	}

	public TransmitType getTransmitType(){
		return this.transmitType;
	}

	public void setTransmitType(TransmitType value) {
		this.transmitType = value;
	}

	/**
	 * 保存前联动计算
	 * <see cref="CommonDtmCollection"/>
	 */
	public CommonDtmCollection getDtmBeforeSave() {

		if (dtmBeforeSave == null) {
			return dtmBeforeSave = new CommonDtmCollection();
		} else {
			return dtmBeforeSave;
		}

	}

	public void setDtmBeforeSave(CommonDtmCollection value) {

		dtmBeforeSave = value;
	}

	/**
	 * 更新后联动计算
	 * <see cref="CommonDtmCollection"/>
	 */
	public CommonDtmCollection getDtmAfterModify() {
		if (dtmAfterModify == null) {
			return dtmAfterModify = new CommonDtmCollection();
		} else {
			return dtmAfterModify;
		}

	}

	public void setDtmAfterModify(CommonDtmCollection value) {

		dtmAfterModify = value;
	}

	/**
	 * 新建后联动计算
	 * <see cref="CommonDtmCollection"/>
	 */
	public CommonDtmCollection getDtmAfterCreate() {
		if (dtmAfterCreate == null) {
			return dtmAfterCreate = new CommonDtmCollection();
		} else {
			return dtmAfterCreate;
		}

	}

	public void setDtmAfterCreate(CommonDtmCollection value) {
		dtmAfterCreate = value;

	}

	/**
	 * 保存前校验规则
	 * <see cref="CommonValCollection"/>
	 */
	public CommonValCollection getValBeforeSave() {
		return UdtUtils.convertToCommonValidations(getValidations(), UdtTriggerTimePointType.BeforeSave);

	}

	public void setValBeforeSave(CommonValCollection value) {
		throw new RuntimeException("业务字段中无法赋值属性[ValBeforeSave]");

	}

	/**
	 * 更新后校验规则
	 * <see cref="CommonValCollection"/>
	 */
	public CommonValCollection getValAfterModify() {
		return UdtUtils.convertToCommonValidations(getValidations(), UdtTriggerTimePointType.AfterModify);

	}

	public void setValAfterModify(CommonValCollection value) {
		throw new RuntimeException("业务字段中无法赋值属性[ValAfterModify]");

	}

	private ColumnCollection privateColumns;

	/**
	 * 待持久化的字段列表
	 * <see cref="ColumnCollection"/>
	 */
	public ColumnCollection getColumns() {
		return (privateColumns != null) ? privateColumns : (privateColumns = new ColumnCollection());
	}

	/**
	 * 是否启用动态属性集合
	 */
	private boolean privateEnableDynamicProp;

	public final boolean getEnableDynamicProp() {
		return privateEnableDynamicProp;
	}

	public final void setEnableDynamicProp(boolean value) {
		privateEnableDynamicProp = value;
	}

	/**
	 * 动态属性集合持久化构件
	 */
	private MdRefInfo privateDynamicPropRepositoryComp;

	public final MdRefInfo getDynamicPropRepositoryComp() {
		return privateDynamicPropRepositoryComp;
	}

	public final void setDynamicPropRepositoryComp(MdRefInfo value) {
		privateDynamicPropRepositoryComp = value;
	}

	/**
	 * 动态属性集合序列化构件
	 */
	private java.util.ArrayList<MdRefInfo> privateDynamicPropSerializerComps;

	public final java.util.ArrayList<MdRefInfo> getDynamicPropSerializerComps() {
		return privateDynamicPropSerializerComps;
	}

	public final void setDynamicPropSerializerComps(java.util.ArrayList<MdRefInfo> value) {
		privateDynamicPropSerializerComps = value;
	}

	private String privateI18nResourceInfoPrefix;

	public final String getI18nResourceInfoPrefix() {
		return privateI18nResourceInfoPrefix;
	}

	public final void setI18nResourceInfoPrefix(String value) {
		privateI18nResourceInfoPrefix = value;
	}

	//TODO 暂不实现udt的运行时定制
	@Override
	public CustomizationInfo getCustomizationInfo() {
		return null;
	}

	@Override
	public void setCustomizationInfo(CustomizationInfo customizationInfo) {

	}

	// endregion

	// region 方法
	protected final UseTypeInfo getUseType(String propertyName) {
		UseTypeInfo tempVar = new UseTypeInfo();
		tempVar.setPropertyName(propertyName);
		return tempVar;
	}

	protected final UseTypeInfo getUseType(String propertyName, UseType type) {
		UseTypeInfo tempVar = new UseTypeInfo();
		tempVar.setPropertyName(propertyName);
		tempVar.setPropertyUseType(type);
		return tempVar;
	}

	/**
	 * 获取属性使用方式信息
	 *
	 * @param propertyName 属性名
	 * @param type         类型
	 * @param canEdit      可编辑
	 * @return <see cref="UseTypeInfo"/>
	 */
	protected final UseTypeInfo getUseType(String propertyName, UseType type, boolean canEdit) {
		UseTypeInfo tempVar = new UseTypeInfo();
		tempVar.setPropertyName(propertyName);
		tempVar.setPropertyUseType(type);
		tempVar.setCanEdit(canEdit);
		return tempVar;
	}

	/**
	 * 获取属性值
	 *
	 * @param propertyName  属性名称
	 * @param propertyType  属性类型
	 * @param propertyValue 属性值
	 * @param type          使用方式
	 * @param canEdit       是否允许编辑
	 * @return <see cref="UseTypeInfo"/>
	 */
	protected final PropertyInfo getPropertyInfo(String propertyName, Class propertyType, Object propertyValue, UseType type, boolean canEdit) {
		PropertyInfo tempVar = new PropertyInfo();
		tempVar.setPropertyName(propertyName);
		tempVar.setPropertyType(propertyType);
		tempVar.setPropertyValue(propertyValue);
		tempVar.setPropertyUseType(type);
		tempVar.setCanEdit(canEdit);
		return tempVar;
	}

	protected final PropertyInfo getPropertyInfo(String propertyName, Class propertyType, Object propertyValue, UseType type) {
		PropertyInfo tempVar = new PropertyInfo();
		tempVar.setPropertyName(propertyName);
		tempVar.setPropertyType(propertyType);
		tempVar.setPropertyValue(propertyValue);
		tempVar.setPropertyUseType(type);
		return tempVar;
	}

	protected final PropertyInfo getPropertyInfo(String propertyName, Class propertyType, boolean canEdit) {
		PropertyInfo tempVar = new PropertyInfo();
		tempVar.setPropertyName(propertyName);
		tempVar.setPropertyType(propertyType);
		tempVar.setCanEdit(canEdit);

		return tempVar;
	}

	/**
	 * 获取生成的Udt实体的类名
	 *
	 * @return <see cref="string"/>
	 */
	public final String getUdtEntityClassName() {
		return getCode() + "UdtEntity";
	}

	/**
	 * 获取生成的UdtManager的类名
	 *
	 * @return
	 */
	public String getManagerClassName() {
		//return getCode()+"UdtManager";
		return getCode().concat("UdtManager");
	}

	private static final String entityNamespaceSuffix = "entity";

	private final String getLowerCaseCode() {
		return this.getCode().toLowerCase();
	}

	/**
	 * 获取entity程序集信息
	 *
	 * @return entity程序集信息
	 */
	public final DataTypeAssemblyInfo getEntityAssemblyInfo() {
		String assName = String.format("%1$s.%2$s.%3$s", getAssemblyName(), getLowerCaseCode(), entityNamespaceSuffix);
		return new DataTypeAssemblyInfo(assName, assName);
	}

	private static final String apiNamespaceSuffix = "api";


	/**
	 * 获取api程序集信息
	 *
	 * @return 程序集名
	 */
	public final DataTypeAssemblyInfo getApiNamespace() {
		String assName = String.format("%1$s.%2$s.%3$s", getAssemblyName(), getLowerCaseCode(), apiNamespaceSuffix);
		return new DataTypeAssemblyInfo(assName, assName);
	}

	private static final String coreNamespacceSuffix = "core";

	/**
	 * 获取core程序集信息
	 *
	 * @return
	 */
	public final DataTypeAssemblyInfo getCoreAssemblyInfo() {
		String assName = String.format("%1$s.%2$s.%3$s", getAssemblyName(), getLowerCaseCode(), coreNamespacceSuffix);
		return new DataTypeAssemblyInfo(assName, assName);
	}

	/**
	 * 获取repository程序集信息
	 *
	 * @return repository程序集信息
	 */
	public final DataTypeAssemblyInfo getRepositoryAssemblyInfo() {
		String assName = String.format("%1$s.%2$s.%3$s", getAssemblyName(), getLowerCaseCode(), "repository");
		return new DataTypeAssemblyInfo(assName, assName);
	}

	/**
	 * 更新待持久化的字段列表
	 */
	public void updateColumnsInfo() {
	}

	/**
	 * 克隆方法
	 *
	 * @return <see cref="object"/>
	 */
	public UnifiedDataTypeDef clone() {
		Object tempVar = null;
		try {
			tempVar = super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}

		return (UnifiedDataTypeDef) ((tempVar instanceof UnifiedDataTypeDef) ? tempVar : null);
	}

	/**
	 * 根据id查找字段
	 *
	 * @param id
	 * @return
	 */
	public IGspCommonField findElement(String id) {
		for (IGspCommonField item : getContainElements()) {
			if (id.equals(item.getID())) {
				return item;
			}
		}
		return null;
	}

	/**
	 * 获取udt类型名
	 *
	 * @return udt类型名
	 */
	public final String getUdtType() {
		return this.getAssemblyName() + "." + getCode();
	}

	public final String getDotnetUdtType() {
		return String.format(this.getDotnetAssemblyName() + "." + getCode());
	}

	/**
	 * 获取entity程序集的类信息
	 *
	 * @return entity程序集的类信息
	 */
	public ClassInfo getGeneratedEntityClassInfo() {
		DataTypeAssemblyInfo assembly = this.getEntityAssemblyInfo();
		String classNamespace = assembly.getDefaultNamespace();
		String className = String.format("I%1$s", getCode());
		return new ClassInfo(assembly, className, classNamespace);
	}
	// endregion

	// region ValueObject,ValueObjectType
	@Override
	public String getUri() {
		return null;
	}

	@Override
	public List<StructuredType> getStructuredTypes() {
		List<StructuredType> list = new ArrayList<>();
		list.add(this);
		buildElementStructureTypes(list);
		return list;
	}

	protected void buildElementStructureTypes(List<StructuredType> list) {

	}

	@Override
	public List<CommonStructure> getRefStructures() {
		return UdtCommonStructureUtil.getInstance().getElementsRefStructures(getContainElements());
	}

	@Override
	public String getKind() {
		// udt继承ValueObject,ValueObjectType,此处返回ValueObject，由cmp特殊处理
		return new DefaultValueObject().getKind();
	}

	@Override
	public List<Property> getProperties() {
		List<Property> list = new ArrayList<Property>();
		for (IGspCommonField field : getContainElements()) {
			list.add((GspCommonField) field);
		}
		return list;
	}

	@Override
	public ValueObjectType getDataType() {
		return this;
	}

	@Override
	public List<Operation> getOperations() {
		return new ArrayList<>();
	}

	@Override
	public List<String> getExtensionKeys() {
		return null;
	}

	@Override
	public String getExtensionValue(String s) {
		return null;
	}

	public Map<String, BaseUdtExtension> getUdtExtensions() {
		return udtExtensions;
	}
	// endregion
}
